package com.youdianda.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youdianda.constant.MessageConstant;
import com.youdianda.dto.SysRoleDTO;
import com.youdianda.dto.SysRolePageDTO;
import com.youdianda.entity.SysMenu;
import com.youdianda.entity.SysRole;
import com.youdianda.entity.SysRoleMenu;
import com.youdianda.entity.SysUser;
import com.youdianda.mapper.SysRoleMenuMapper;
import com.youdianda.result.PageResult;
import com.youdianda.result.Result;
import com.youdianda.service.SysMenuService;
import com.youdianda.service.SysRoleMenuService;
import com.youdianda.service.SysRoleService;
import com.youdianda.mapper.SysRoleMapper;
import com.youdianda.service.SysUserService;
import com.youdianda.vo.SysMenuVO;
import com.youdianda.vo.SysRoleVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
* @author xliu
* @description 针对表【sys_role(角色表)】的数据库操作Service实现
* @createDate 2023-05-14 16:01:07
*/
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole>
    implements SysRoleService{

    @Autowired
    private SysRoleMenuMapper sysRoleMenuMapper;

    @Autowired
    private SysRoleMenuService sysRoleMenuService;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SysRoleMapper sysRoleMapper;

    @Autowired
    private SysMenuService sysMenuService;

    /**
     * 角色分页查询
     * @param sysRolePageDTO
     * @return
     */
    @Override
    public Result listRolePage(SysRolePageDTO sysRolePageDTO) {
        if (sysRolePageDTO.getPage() == null) {
            sysRolePageDTO.setPage("1");
        }
        if (sysRolePageDTO.getLimit() == null) {
            sysRolePageDTO.setLimit("10");
        }
        long current = Long.parseLong(sysRolePageDTO.getPage());
        long size = Long.parseLong(sysRolePageDTO.getLimit());
        // 分页条件模糊查询
        IPage<SysRole> page = new Page<>(current, size);
        this.page(page, Wrappers.<SysRole>lambdaQuery()
                .like(org.springframework.util.StringUtils.hasLength(sysRolePageDTO.getName()),
                    SysRole::getName, sysRolePageDTO.getName())
                .orderByDesc(SysRole::getUpdate_date)
        );
        // 得到查询结果
        List<SysRole> sysRoles = page.getRecords();
        List<SysRoleVO> sysRoleVOS = new ArrayList<>();
        // 遍历
        for (SysRole sysRole : sysRoles) {
            // 创建角色vo
            SysRoleVO sysRoleVO = new SysRoleVO();
            // 将角色对象数据复制到vo中
            BeanUtils.copyProperties(sysRole, sysRoleVO);
            // 根据角色id查询对应的菜单id列表
            List<String> menuIds = sysRoleMenuMapper.listMenuIdByRoleId(sysRole.getId());
            // 给角色vo的角色菜单列表和角色id赋值
            sysRoleVO.setRole_menus(StringUtils.join(menuIds, ","));
            sysRoleVO.setRole_id(sysRole.getId());

            sysRoleVOS.add(sysRoleVO);
        }
        // 封装数据，返回
        PageResult pageResult = new PageResult((int) page.getTotal(), (int)  page.getPages(), (int)  page.getCurrent(),
                (int)  page.getSize(), sysRoleVOS);
        return Result.success(pageResult);
    }

    /**
     * 角色修改
     * @param sysRoleDTO
     * @return
     */
    @Transactional
    @Override
    public Result updateRole(SysRoleDTO sysRoleDTO) {
        String roleId = sysRoleDTO.getId();
        String name = sysRoleDTO.getName();
        String description = sysRoleDTO.getDescription();
        if (!org.springframework.util.StringUtils.hasLength(roleId)) {
            return Result.error(MessageConstant.ID_NOT_FOUND);
        }
        if (!org.springframework.util.StringUtils.hasLength(sysRoleDTO.getName())) {
            return Result.error(MessageConstant.ROLE_NAME_NOT_FOUND);
        }
        // 根据角色名查询角色
        SysRole sysRole = getOne(Wrappers.<SysRole>lambdaQuery().eq(SysRole::getName, sysRoleDTO.getName())
                .ne(SysRole::getId, roleId));
        // 判断角色名是否重复
        if (sysRole != null) {
            return Result.error(MessageConstant.ROLE_NAME_ALREADY_EXIST);
        }
        // 创建LambdaUpdateWrapper对象，动态修改角色表数据
        LambdaUpdateWrapper<SysRole> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.set(org.springframework.util.StringUtils.hasLength(name), SysRole::getName, name);
        updateWrapper.set(org.springframework.util.StringUtils.hasLength(description), SysRole::getDescription, description);
        updateWrapper.set(SysRole::getUpdate_date, LocalDateTime.now());
        updateWrapper.eq(SysRole::getId, roleId);
        update(updateWrapper);
        // 根据roleId删除角色菜单数据
        sysRoleMenuMapper.deleteByRoleId(roleId);
        List<Number> menuids = sysRoleDTO.getMenuids();
        // 批量添加角色菜单表数据
        List<SysRoleMenu> sysRoleMenus = menuids.stream().map(menuid -> new SysRoleMenu(roleId, menuid.toString()))
                .collect(Collectors.toList());
        sysRoleMenuService.saveBatch(sysRoleMenus);

        return Result.success();
    }

    /**
     * 根据id查询角色详情
     * @param id
     * @return
     */
    @Override
    public Result getRoleById(String id) {
        // 非空校验
        if (!org.springframework.util.StringUtils.hasLength(id)) {
            return Result.error(MessageConstant.ID_NOT_FOUND);
        }
        // 根据id查询角色信息
        SysRole sysRole = getById(id);
        SysRoleVO sysRoleVO = new SysRoleVO();
        if (sysRole != null) {
            // 封装vo
            BeanUtils.copyProperties(sysRole, sysRoleVO);
            // 设置菜单类列表
            sysRoleVO.setAuthList(listSysMenuByRoleId(id));
        }

        return Result.success(sysRoleVO);
    }

    /**
     * 查询全部角色数据
     * @return
     */
    @Override
    public Result listAllRole() {

        return Result.success(list());
    }

    /**
     * 角色添加
     * @param sysRoleDTO
     * @return
     */
    @Override
    @Transactional
    public Result addRole(SysRoleDTO sysRoleDTO) {
        if (!org.springframework.util.StringUtils.hasLength(sysRoleDTO.getName())) {
            return Result.error(MessageConstant.ROLE_NAME_NOT_FOUND);
        }
        // 根据角色名查询角色
        SysRole sysRole = getOne(Wrappers.<SysRole>lambdaQuery().eq(SysRole::getName, sysRoleDTO.getName()));
        // 判断角色名是否重复
        if (sysRole != null) {
            return Result.error(MessageConstant.ROLE_NAME_ALREADY_EXIST);
        }
        // 设置角色数据
        sysRole = new SysRole();
        BeanUtils.copyProperties(sysRoleDTO, sysRole);
        sysRole.setCreate_date(LocalDateTime.now());
        sysRole.setUpdate_date(LocalDateTime.now());
        // 添加角色数据
        save(sysRole);
        // 添加角色菜单数据
        String roleId = sysRole.getId();
        sysRoleMenuService.saveBatch(sysRoleDTO.getMenuids()
                .stream().map(menuid -> new SysRoleMenu(roleId, menuid.toString()))
                .collect(Collectors.toList()));
        return Result.success();
    }

    /**
     * 根据id删除角色
     * @param id
     * @return
     */
    @Override
    @Transactional
    public Result deleteRoleById(String id) {
        // 非空校验
        if (!org.springframework.util.StringUtils.hasLength(id)) {
            return Result.error(MessageConstant.ID_NOT_FOUND);
        }
        // 查询系统用户的角色id是否包含当前角色id
        List<SysUser> sysUsers = sysUserService.list(Wrappers.<SysUser>lambdaQuery().like(SysUser::getRole_id, id));
        if (sysUsers != null && sysUsers.size() > 0) {
            return Result.error("当前角色正在被使用, 不能删除");
        }
        // 逻辑删除角色
        removeById(id);
        // 批量删除角色菜单
        sysRoleMenuMapper.delete(Wrappers.<SysRoleMenu>lambdaQuery().eq(SysRoleMenu::getRole_id, id));
        return Result.success();
    }


    /**
     * 所有菜单列表
     * @return
     */
    public List<SysMenuVO> listSysMenuByRoleId(String id) {
        // 根据角色id查询菜单信息
        List<SysMenu> sysMenus = sysRoleMapper.listMenuByRoleId(id);

        List<SysMenuVO> sysMenuVOS = new ArrayList<>();
        for (SysMenu sysMenu : sysMenus) {
            SysMenuVO sysMenuVO = new SysMenuVO();
            BeanUtils.copyProperties(sysMenu, sysMenuVO);
            sysMenuVOS.add(sysMenuVO);
        }

        // 第一级菜单
        List<SysMenuVO> firstLevelMenus = sysMenuVOS.stream().filter(sysMenuVO -> sysMenuVO.getPid() == 0).collect(Collectors.toList());
        if (firstLevelMenus != null && firstLevelMenus.size() > 0) {
            for (SysMenuVO firstMenu : firstLevelMenus) {
                // 第二级菜单
                List<SysMenuVO> secondLevelMenus = sysMenuVOS.stream().filter(sysMenuVO -> sysMenuVO.getPid() == firstMenu.getId()).collect(Collectors.toList());
                if (secondLevelMenus != null && secondLevelMenus.size() > 0) {
                    for (SysMenuVO secondMenu : secondLevelMenus) {
                        // 第三级菜单
                        List<SysMenuVO> thirdLevelMenu = sysMenuVOS.stream().filter(sysMenuVO -> sysMenuVO.getPid() == secondMenu.getId()).collect(Collectors.toList());
                        if (thirdLevelMenu != null && thirdLevelMenu.size() > 0) {
                            for (SysMenuVO thirdMenu : thirdLevelMenu) {
                                List<SysMenuVO> fourthLevelMenu = sysMenuVOS.stream().filter(sysMenuVO -> sysMenuVO.getPid() == thirdMenu.getId()).collect(Collectors.toList());
                                thirdMenu.setChildren(fourthLevelMenu);
                            }
                        }
                        secondMenu.setChildren(thirdLevelMenu);
                    }
                }
                firstMenu.setChildren(secondLevelMenus);
            }
        }

        return firstLevelMenus;
    }
}




